package zb.md2html.gen;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import jodd.bean.BeanTemplateParser;
import jodd.io.FileUtil;
import jodd.template.MapTemplateParser;
import jodd.util.Wildcard;
import kits.my.BufferKit;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Synchronized;
import lombok.val;
import lombok.extern.slf4j.Slf4j;
import zb.md2html.type.MdPreType;
import zb.md2html.type.MdTableType;

/**
 * h2标签内容的生成
 * 
 * @author Administrator
 *
 */
@Slf4j
@RequiredArgsConstructor
public class H2 extends ZbBase {
	private @NonNull List<String> mdLines;
	
	
	//<button class="s-btn selected" data-res="json">JSON示例</button>
	private final String menu = "<button class='s-btn{}' data-res='{}'>{}</button>";
	private final String selectClass = " selected";

	public H2Info getH2() throws IOException {
		val params = new HashMap<String, String>();
//		params.put("urlRequest", this.toRequest());
		params.put("response", this.toResponseJson());// 改需求,作废
		params.put("requestTable", this.formatTable(MdTableType.请求参数));
		params.put("responseTable", this.getResultCode());

		params.put("title", this.getTitle());
//		params.put("lanCode", this.toLanCode());// 代码块 旧的
		params.put("lanCode", this.toLanCodeNew());// 代码块
		String BASE_CHAR = "abcdefghijklmnopqrstuvwxyz";
		val id = RandomUtil.randomString(BASE_CHAR, 15);
		params.put("titleId", id);
		val html = new MapTemplateParser().of(params).parse(FileUtil.readString(fileH2));
		return new H2Info(id, html);
	}

	@Data
	@AllArgsConstructor
	public static class H2Info {
		private String id;
		private String html;
	}

	public String getTitle() {
		for (val line : mdLines) {
			if (Wildcard.matchPath(line, "##*")) {// end
				return line.replace("##", "").trim();
			}
		}
		return null;
	}

	private String formatTable(MdTableType mdTableType) throws IOException {
		val table = this.getMdTable(mdTableType, mdLines);
		val tr = table.getTr();
		if (tr == null) {
			return "";
		}

		val sb = new BufferKit();
		table.getTds().forEach(td -> {
			String tdStr = new BeanTemplateParser().of(td).parse(tdRequest);
			sb.append(tdStr);
		});
		val params = new HashMap<String, String>();
		params.put("tr", new BeanTemplateParser().of(tr).parse(trRequest));
		params.put("tds", sb.toString());
		return new MapTemplateParser().of(params).parse(FileUtil.readString(tableTemplate));
	}
	
	Boolean frist = true;
	/**
	 * 代码块生成,包含标签页
	 * @return
	 */
	@Synchronized
	private String toLanCodeNew() {
		
		val html = new BufferKit();
		//代码块按钮
		val menuHtml = new BufferKit();
		languages.forEach(lan -> {
			
			val sb = new BufferKit();
			// 备注下源码类型
			sb.append("// {} demo", lan.name());
			this.getMdJson(lan).forEach(line -> {
				// 注释加上高亮(整行)
				sb.append(line);
			});
			// 进行关键字高亮处理
			String pre = sb.toString();
			for (String hl : highlight) {
				pre = ReUtil.replaceAll(pre, hl, height);
			}
			val params = new HashMap<String, String>();
			if(frist) {//第一次,默认第一个语言选中
				params.put("selectClass", selectClass);
				menuHtml.append(menu,selectClass,lan.name().toLowerCase(),lan.name().toUpperCase());
				
				frist = false;
			}else {
				menuHtml.append(menu,"",lan.name().toLowerCase(),lan.name().toUpperCase());
			}
			params.put("content", pre);
			params.put("language", lan.name());
			try {
				String preHtml = new MapTemplateParser().of(params).parse(FileUtil.readString(response_noLan));
				//处理prehtml,进行高亮操作
				FileUtil.writeString(tempFile, preHtml);
				val remarks = new BufferKit();
				Arrays.asList(FileUtil.readLines(tempFile)).forEach(line -> {
					//高亮:注释
					if (Wildcard.matchPath(line.trim(), "//*") || Wildcard.matchPath(line.trim(), "*加密类*") || Wildcard.matchPath(line.trim(), "#*")) {
						line = StrUtil.format(zhushiTemp, line);
					}
					remarks.append(line);
				});
				//得到已经高亮的pre并且放入 switch-body
				String preFinal = remarks.toString();
				params.put("pre", preFinal);
				String switchBodyHtml = new MapTemplateParser().of(params).parse(FileUtil.readString(switchBody));
				html.append(switchBodyHtml);
			} catch (IOException e) {
				log.error("代码块生成异常switchBody", e);
			}
		});
		String switchWrapperHtml = null;
		try {
			val params = new HashMap<String, String>();
			params.put("switchBodys", html.toString());
			params.put("menus", menuHtml.toString());
			params.put("title","请求示例");
			switchWrapperHtml= new MapTemplateParser().of(params).parse(FileUtil.readString(switchWrapper));
			
		} catch (IOException e) {
			log.error("代码块生成异常switchWrapper", e);
		}
		return switchWrapperHtml;
	}

	/**
	 * 代码块生成 (新需求,废弃)
	 * 
	 * @return html
	 */
	@Synchronized
	@Deprecated
	private String toLanCode() {
		val html = new BufferKit();
		languages.forEach(lan -> {
			val sb = new BufferKit();
			// 备注下源码类型
			sb.append("// {} demo", lan.name());
			this.getMdJson(lan).forEach(line -> {
				// 注释加上高亮(整行)
				sb.append(line);
			});
			// 进行关键字高亮处理
			String pre = sb.toString();
			for (String hl : highlight) {
				pre = ReUtil.replaceAll(pre, hl, height);
			}
			val params = new HashMap<String, String>();
			params.put("content", pre);
			params.put("language", lan.name());
			try {
				String parse = new MapTemplateParser().of(params).parse(FileUtil.readString(fileResponse));
				FileUtil.writeString(tempFile, parse);
				val remarks = new BufferKit();

				Arrays.asList(FileUtil.readLines(tempFile)).forEach(line -> {
					if (Wildcard.matchPath(line.trim(), "//*") || Wildcard.matchPath(line.trim(), "*加密类*")) {
						line = StrUtil.format(zhushiTemp, line);
					}
					remarks.append(line);
				});
				html.append(remarks.toString());
			} catch (IOException e) {
				log.error("代码块生成异常", e);
			}
		});
		return html.toString();
	}

	/**
	 * 获取返回值说明
	 * 
	 * @return
	 * @throws IOException
	 */
	private String getResultCode() throws IOException {
		val sb = new BufferKit();
		this.getMdJson(MdPreType.resdata).forEach(line -> {
			if (!Wildcard.matchPath(line, "*:*")) {
				return;
			}
			String[] split = line.split(":");
			if (split.length != 2) {
				return;
			}
			String key = split[0].trim();
			String value = split[1].trim();
			sb.append(tdResponse, key, value);
		});
		val params = new HashMap<String, String>();
		params.put("tr", StrUtil.format(trResponse, "返回值", "描述"));
		params.put("tds", sb.toString());
		return new MapTemplateParser().of(params).parse(FileUtil.readString(tableTemplate));
	}

	/**
	 * 返回生成好的json request
	 * 
	 * 需求变了,作废
	 * 
	 * @return
	 * @throws IOException
	 */
	private String toResponseJson() throws IOException {
		val javacode = this.getMdJson(MdPreType.response);
		javacode.add(0, "// 返回结果");
		val sb = new BufferKit();
		javacode.forEach(jc -> {
			String[] split = jc.split(":");
			if (split.length == 2) {
				String key = split[0].replaceAll("\"", "'");
				String val = split[1].replaceAll("\"", "'");
				sb.append(StrUtil.format(ntTemp, key, val));
			} else {
				sb.append(StrUtil.format(pTemp, jc));
			}
		});
		val params = new HashMap<String, String>();
		params.put("content", sb.toString());
		params.put("language", MdPreType.json.name());
		String pre = new MapTemplateParser().of(params).parse(FileUtil.readString(response_noLan));
		
		params.put("pre", pre);
		params.put("selectClass", selectClass);
		String switchBodyHtml = new MapTemplateParser().of(params).parse(FileUtil.readString(switchBody));
		
		params.put("switchBodys", switchBodyHtml);
		params.put("title","响应示例");
		params.put("menus", StrUtil.format(menu,selectClass, "json","JSON"));
		String html = new MapTemplateParser().of(params).parse(FileUtil.readString(switchWrapper));
		html = html.replaceAll("'", "\"");
		return html;
	}

	/**
	 * 获取md中的json代码块
	 * 
	 * @param mdLines
	 * @return
	 */
	private List<String> getMdJson(MdPreType mdType) {
		boolean run = false;
		val list = new ArrayList<String>();
		for (val line : mdLines) {
			if (Wildcard.matchPath(line, "```")) {// end
				run = false;
			}
			if (run) {
				list.add(line);
			}
			if (Wildcard.matchPath(line, "```" + mdType.name() + "*")) {// start
				run = true;
			}
		}
		return list;
	}

}
